home *** CD-ROM | disk | FTP | other *** search
/ Aminet 4 / Aminet 4 - November 1994.iso / aminet / comm / net / amitcp_ups10.lha / orig / ups.c < prev    next >
C/C++ Source or Header  |  1993-10-03  |  10KB  |  565 lines

  1. #ifndef lint
  2. static char RCSid[] = "$Header: ups.c,v 1.8 86/12/11 15:58:18 scooter Exp $";
  3. #endif
  4.  
  5. /*
  6.  * ups - user interface to the package delivery system
  7.  *
  8.  * usage: ups user@host file1 file2 ...
  9.  *
  10.  * $Author: scooter $
  11.  * $Revision: 1.8 $
  12.  * $Date: 86/12/11 15:58:18 $
  13.  *
  14.  * $Log:    ups.c,v $
  15.  * Revision 1.8  86/12/11  15:58:18  scooter
  16.  * Added alias expansion code which allows ups to follow /usr/lib/aliases.
  17.  * 
  18.  * Revision 1.7  86/09/19  18:53:15  scooter
  19.  * Added -i option for mail specification
  20.  * 
  21.  * Revision 1.6  86/09/18  15:19:45  scooter
  22.  * More fixes to the '.' problam
  23.  * 
  24.  * Revision 1.5  86/09/17  09:43:38  scooter
  25.  * Added code to do automatic renaming of "." files for delivery to
  26.  * avoid the "cannot delete" problem
  27.  * 
  28.  * Revision 1.4  85/08/21  22:27:45  scooter
  29.  * Release revision: added more complete RCS headers.
  30.  * 
  31.  */
  32.  
  33. #include <stdio.h>
  34. #include <pwd.h>
  35. #include <ndbm.h>
  36. #include <sys/wait.h>
  37. #include <sys/types.h>
  38. #include <sys/stat.h>
  39. #include <sys/socket.h>
  40. #include <sys/file.h>
  41. #include <netinet/in.h>
  42. #include <netdb.h>
  43. #include <ctype.h>
  44.  
  45. #define    LS "/bin/ls"
  46.  
  47. struct    passwd *getpwuid();
  48. FILE     *fopen();
  49. int    rem;
  50. int    qflg = 0;
  51. int    iflg = 0;
  52. int    on   = 1;
  53. char    buffer[BUFSIZ*5];
  54. char    mbuffer[BUFSIZ*4];
  55.  
  56. struct    user_list {
  57.     char    *u_user;
  58.     char    *u_host;
  59.     struct    user_list *u_next;
  60. };
  61.  
  62. main(argc, argv)
  63. char **argv;
  64. int argc;
  65. {
  66.     char    myhost[BUFSIZ];
  67.     int    file;
  68.     int    ret;
  69.     char    *user,*host,*tmp,*rindex(),*index();
  70.     struct    passwd *mypwent;
  71.     struct    user_list *u_list,*u_top, *alias_expand();
  72.  
  73.     gethostname(myhost,BUFSIZ);
  74.  
  75.     if( (mypwent = getpwuid(getuid())) == NULL )
  76.     {
  77.         fprintf(stderr,"ups: who are you?\n");
  78.         exit(1);
  79.     }
  80.  
  81.     argv++;
  82.     argc--;
  83.     while (argc && *argv[0] == '-')
  84.     {
  85.         char     c;
  86.  
  87.         switch (c = argv[0][1])
  88.         {
  89.  
  90.         case 'q':
  91.             qflg++;
  92.             break;
  93.  
  94.         case 'i':
  95.             iflg++;
  96.             break;
  97.  
  98.         default:
  99.             fprintf(stderr,"ups: unknown option %c\n",c);
  100.  
  101.         }
  102.         argv++;
  103.         argc--;
  104.     }
  105.  
  106.     if (argc <= 1 || qflg)
  107.         upsread(mypwent);
  108.  
  109.     if (argc < 2) {
  110.         fprintf(stderr,"usage: ups user@host file1 file2 ...\n");
  111.         exit(0);
  112.     }
  113.  
  114.     /*
  115.  * Get the name of the destination user and host
  116.  */
  117.  
  118.     user = argv[0];
  119.     host = rindex(user,'@');
  120.     fprintf(stderr, "user = %s\n", user);
  121. #ifndef    ALIASES
  122.     if (host == NULL)
  123.         host = myhost;
  124.     else
  125.         *host++ = '\0';
  126. #else
  127.     if (host != NULL)
  128.         *host++ = '\0';
  129.  
  130.     u_top = alias_expand(user,host,myhost);
  131.  
  132. #endif    ALIASES
  133.  
  134. #ifdef DEBUG
  135.     printf("Here we are again\n");
  136. #endif
  137.  
  138.     if (iflg)
  139.         upsgetmsg(mbuffer);
  140.     else
  141.         mbuffer[0] = '\0';
  142.  
  143.     while (u_top != NULL)
  144.     {
  145.  
  146. #ifdef    DEBUG
  147.         printf("Connecting to %s for user %s\n",u_top->u_host,u_top->u_user);
  148. #endif
  149.         rem = upsconnect(u_top->u_host);    /* Connect to the server */
  150.  
  151.         /*
  152.          * Send the to name, from name, and our name
  153.          */
  154.  
  155.         tmp = index(mypwent->pw_gecos,',');
  156.         if (tmp)
  157.             *tmp = '\0';
  158.  
  159.         sprintf(buffer, "%s\n%s\n%s\n%s", u_top->u_user,
  160.             mypwent->pw_name, mypwent->pw_gecos,mbuffer);
  161.  
  162. #ifdef    DEBUG
  163.         printf("Sending: %s\n",buffer);
  164.         fflush(stdout);
  165. #endif    DEBUG
  166.  
  167.         write(rem, buffer, strlen(buffer)+1);
  168.         ret = read(rem, buffer, BUFSIZ);
  169.         if (buffer[0])
  170.             problem(1);
  171.  
  172.         for (file = 1 ; file < argc ; file++)
  173.         {
  174.  
  175. #ifdef    DEBUG
  176.             printf("Sending file: %s\n",argv[file]);
  177. #endif    DEBUG
  178.  
  179.             sendfile(argv[file]);
  180.         }
  181.  
  182.         sprintf(buffer, "-Done-");
  183.         write(rem, buffer, strlen(buffer)+1);
  184.         read(rem, buffer, BUFSIZ);    /* get result */
  185.         if (buffer[0])        /* problem? */
  186.             problem(1);    /* yes, go handle it */
  187.  
  188.         close(rem);
  189.         u_top = u_top->u_next;
  190.     }
  191.  
  192. }
  193.  
  194.  
  195.  
  196.  
  197. upsconnect(host)
  198. char *host;
  199. {
  200.     struct hostent *hp;
  201.     struct servent *sp;
  202.     struct    sockaddr_in sin;
  203.     int s;
  204.  
  205.     hp = gethostbyname(host);
  206.     if (hp == NULL) {
  207.         static struct hostent def;
  208.         static struct in_addr defaddr;
  209.         static char namebuf[128];
  210.         int inet_addr();
  211.  
  212.         defaddr.s_addr = inet_addr(host);
  213.         if (defaddr.s_addr == -1) {
  214.             printf("unknown host: %s\n", host);
  215.             exit(1);
  216.         }
  217.         strcpy(namebuf, host);
  218.         def.h_name = namebuf;
  219.         def.h_addr = (char *)&defaddr;
  220.         def.h_length = sizeof (struct in_addr);
  221.         def.h_addrtype = AF_INET;
  222.         def.h_aliases = 0;
  223.         hp = &def;
  224.     }
  225.     sp = getservbyname("ups", "tcp");
  226.     if (sp == 0) {
  227.         fprintf(stderr,"tcp/ups: unknown service\n");
  228.         exit(1);
  229.     }
  230.     sin.sin_family = hp->h_addrtype;
  231.     bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
  232.     sin.sin_port = sp->s_port;
  233.     s = socket(hp->h_addrtype, SOCK_STREAM, 0);
  234.     if (s < 0) {
  235.         fflush(stderr);
  236.         perror("ups (socket)");
  237.         exit(1);
  238.     }
  239.     setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,&on,sizeof(on));
  240. #ifdef    DEBUG
  241.     setsockopt(s,SOL_SOCKET,SO_DEBUG,&on,sizeof(on));
  242. #endif    DEBUG
  243.     if (connect(s, (char *)&sin, sizeof (sin)) < 0) {
  244.         fflush(stderr);
  245.         perror("ups (connect)");
  246.         close(s);
  247.         exit(1);
  248.     }
  249.     return(s);
  250. }
  251.  
  252.  
  253.  
  254.  
  255. sendfile(file)
  256. char *file;
  257. {
  258.     struct    stat fstatus;
  259.     int    loc,n;
  260.     char    *tmp,*fname;
  261.  
  262.     if ( (loc = open(file,O_RDONLY)) <= 0 ) {
  263.         perror("ups (open)");
  264.         return(1);
  265.     }
  266.     if (fstat(loc, &fstatus)) {
  267.         perror("ups (fstat)");
  268.         return(1);
  269.     }
  270.  
  271.     if ((fstatus.st_mode&S_IFMT) != S_IFREG) {
  272.         switch (fstatus.st_mode&S_IFMT)
  273.         {
  274.         case S_IFDIR:
  275.             tmp = "directory";
  276.             break;
  277.         case S_IFCHR:
  278.             tmp = "character device";
  279.             break;
  280.         case S_IFBLK:
  281.             tmp = "block device";
  282.             break;
  283.         case S_IFLNK:
  284.             tmp = "symbolic link";
  285.             break;
  286.         case S_IFSOCK:
  287.             tmp = "socket";
  288.             break;
  289.         }
  290.  
  291.         fprintf(stderr,
  292.             "ups: %s is a %s, only regular files may be sent\n",
  293.             file,tmp);
  294.         fflush(stderr);
  295.         return(1);
  296.     }
  297.  
  298.     /*
  299.      * Send the file name
  300.      */
  301.  
  302.     /*
  303.      * First strip off the directory path
  304.      */
  305.     sprintf(buffer,"%s",file);
  306.     tmp = rindex(buffer,'/');
  307.     if (tmp)
  308.         *tmp++ = '\0';
  309.     else
  310.         tmp = buffer;
  311.  
  312.     fname = tmp;
  313.  
  314.     if (*tmp == '.')
  315.     {
  316.         while ( (*tmp == '.') && (*tmp != '\0') )tmp++;
  317.  
  318.         fprintf(stdout,
  319.             "WARNING: file %s has been renamed to %s for delivery\n",
  320.             fname,tmp);
  321.     }
  322.  
  323.     write(rem, tmp, strlen(tmp)+1);
  324.     read(rem, buffer, BUFSIZ);
  325.     if (buffer[0])        /* problem */
  326.     {
  327.         problem(0);
  328.         return(1);
  329.     }
  330.  
  331.     /*
  332.      * Send the file size in bytes
  333.      */
  334.  
  335.     sprintf(buffer, "%D",fstatus.st_size);
  336.     write(rem, buffer, strlen(buffer)+1);
  337.     read(rem, buffer, BUFSIZ);
  338.     if (buffer[0])        /* problem */
  339.     {
  340.         problem(0);
  341.         return(1);
  342.     }
  343.  
  344.     /*
  345.      * Send the file
  346.      */
  347.     while (n = read(loc, buffer, BUFSIZ))
  348.         write(rem, buffer, n);
  349.     close(loc);
  350.     read(rem, buffer, BUFSIZ); /* get result */
  351.     if (buffer[0])        /* problem */
  352.     {
  353.         problem(0);
  354.         return(1);
  355.     }
  356.     sprintf(buffer, "%u", fstatus.st_mode);
  357.     write(rem, buffer, strlen(buffer)+1);
  358.     read(rem, buffer, BUFSIZ); /* get result */
  359.     if (buffer[0])        /* problem */
  360.     {
  361.         problem(0);
  362.         return(1);
  363.     }
  364.     return(0);
  365. }
  366.  
  367.  
  368.  
  369. upsread(mypwent)
  370. struct    passwd *mypwent;
  371. {
  372.     union    wait status;
  373.     int    pid;
  374.     char    c,line[BUFSIZ],*tmp;
  375.  
  376.     sprintf(buffer,"%s/%s",UPSDIR,mypwent->pw_name);
  377.     if (qflg)
  378.     {
  379.         if (!access(buffer,F_OK)) {
  380.             fprintf(stderr,
  381.                 "You have ups files awaiting you (type ups to accept delivery)\n");
  382.         }
  383.         exit(0);
  384.     }
  385.     if (access(buffer,F_OK)) {
  386.         fprintf(stderr,"Nothing waiting in ups\n");
  387.         exit(0);
  388.     }
  389.     fprintf(stdout,"\nYou have the following files awaiting delivery:\n\n");
  390.     if (pid = vfork())
  391.     {
  392.         wait(&status);
  393.     } else {
  394.         execl(LS,"ls","-C",buffer,(char *)0);
  395.         perror("ups (exec)");
  396.         return(0);
  397.     }
  398.     fprintf(stdout,"\n");
  399.  
  400.     fprintf(stdout,
  401.         "Do you wish to accept delivery in your\n");
  402.     fprintf(stdout,
  403.         "current directory (%s)? ",
  404.         getwd(line));
  405.  
  406. getinp:
  407.     if (fgets(line,BUFSIZ,stdin) == NULL) {
  408.         fprintf(stdout,"\n");
  409.         exit(0);
  410.     }
  411.  
  412.     tmp = &line[0];
  413.     while (isspace(*tmp)) tmp++;
  414.  
  415.     switch (*tmp) {
  416.     case 'y':
  417.     case 'Y':
  418.         sprintf(line,"mv -i %s/* . ; rmdir %s",buffer,buffer);
  419.         system(line);
  420.         exit(0);
  421.  
  422.     case 'n':
  423.     case 'N':
  424.         exit(0);
  425.  
  426.     default:
  427.         fprintf(stdout,"Please answer 'yes' or 'no': ");
  428.         goto getinp;
  429.     }
  430. }
  431.  
  432.  
  433.  
  434. /*
  435.  * problem() is called when the install demon process return a non-zero reply.
  436.  * This usually means something recognizable went wrong and we should expect
  437.  * a reason to follow. Read in the reason, output it on the terminal and die.
  438.  */
  439.  
  440. problem(die)
  441. int die;
  442. {
  443.     char buf[BUFSIZ];    /* place to read into */
  444.  
  445.     if (read(rem, buf, BUFSIZ) > 0)        /* if we have something */
  446.         fprintf(stderr, "ups: %s", buf);
  447.     if (die) {
  448.         close(rem);        /* close network channel */
  449.         exit(1);
  450.     }
  451. }
  452.  
  453. int
  454. upsgetmsg(mailbuffer)
  455. char *mailbuffer;
  456. {
  457.     int done = 0;
  458.  
  459.     fprintf(stdout,
  460.         "Enter your message followed by '.<RETURN>' or a <CTRL>D:\n");
  461.  
  462.     while (!done)
  463.     {
  464.         fprintf(stdout,"> ");
  465.         if (gets(mailbuffer) == NULL)
  466.         {
  467.             fprintf(stdout,"\n");
  468.             done++;
  469.         } else if ( (*mailbuffer == '.') && (*(mailbuffer+1) == '\0'))
  470.         {
  471.             done++;
  472.             *mailbuffer = '\0';
  473.         } else {
  474.             while(*mailbuffer != '\0')
  475.                 mailbuffer++;
  476.             *mailbuffer++ = '\n';
  477.             *mailbuffer = '\0';
  478.         }
  479.     }
  480.     fprintf(stdout,"[EOT]\n");
  481. }
  482.  
  483.  
  484.  
  485. struct user_list *
  486. alias_expand(user,host,myhost)
  487. char *user,*host,*myhost;
  488. {
  489.     char    *malloc();
  490.     DBM    *dp;
  491.     datum    key,content;
  492.     struct    user_list *list,*top,*alloc_list();
  493.     char    *cp,*tp,*hp;
  494.  
  495.     list = top = (struct user_list *)NULL;
  496.  
  497.     if (host != NULL)
  498.         return(alloc_list(user,host));
  499.  
  500.     dp = dbm_open("/usr/lib/aliases", O_RDONLY, 0644);
  501.  
  502.     if (dp == NULL) {
  503.         if(host == NULL)
  504.             return(alloc_list(user, myhost));
  505.         else
  506.             return(alloc_list(user, host));
  507.     }
  508.  
  509.     key.dptr = user;
  510.     key.dsize = strlen(user) + 1;
  511.  
  512.     content = dbm_fetch(dp,key);
  513.     if (content.dptr == NULL)
  514.         return(alloc_list(user,myhost));
  515.     cp = content.dptr;
  516.  
  517.     while (cp != NULL)
  518.     {
  519.         tp = cp;
  520.         cp = index(cp,',');
  521.         if (cp != NULL)
  522.             *cp++ = '\0';
  523.         if (index(tp,'!')) {
  524.             fprintf(stderr,
  525.                 "ups: WARNING: cannot alias %s to %s (no ups over uucp)\n",
  526.                 user,hp);
  527.             continue;
  528.         } else if(index(tp,'|')) {
  529.             fprintf(stderr,
  530.                 "ups: WARNING: cannot alias %s to %s (no shells allowed)\n",
  531.                 user,hp);
  532.             continue;
  533.         }
  534.         hp = tp;
  535.         hp = index(tp,'@');
  536.         if (hp == NULL)
  537.             hp = myhost;
  538.         else
  539.             *hp++ = '\0';
  540.         if (top == NULL)
  541.             top = list = alloc_list(tp,hp);
  542.         else
  543.         {
  544.             list->u_next = alloc_list(tp,hp);
  545.             list = list->u_next;
  546.         }
  547.     }
  548.     return(top);
  549. }
  550.  
  551. struct    user_list *alloc_list(user,host)
  552. char *user,*host;
  553. {
  554.     char *malloc();
  555.     struct    user_list *list;
  556.  
  557.     list = (struct user_list *)malloc(sizeof(struct user_list));
  558.     list->u_user = malloc(strlen(user) + 1);
  559.     list->u_host = malloc(strlen(host) + 1);
  560.     strcpy(list->u_user,user);
  561.     strcpy(list->u_host,host);
  562.     list->u_next = (struct user_list *)NULL;
  563.     return(list);
  564. }
  565.